using System;
using System.Reflection;
using System.Xml;

namespace XmlObjects.Parsers
{
	public class StringConstructable<T> : Parser<T>
	{
		private ConstructorInfo constructorInfo;

		public StringConstructable()
		{
			Type theType = typeof (T);
			constructorInfo = theType.GetConstructor(new Type[] {typeof (string)});
		}

		public override  T GetValue(XmlNode node)
		{
			XmlNode localNode = node.SelectSingleNode(SelectString);
			string value = GetInnerXml(localNode);
			if (value == null)
				return default(T);
			else
				return GetValueLocal(localNode);
		}

		public override T GetValueLocal(XmlNode node)
		{
			return (T)constructorInfo.Invoke(new object[] { node.InnerXml });
		}
	}


	public class Parseable<T> : Parser<T>
	{
		private object theObject;
		private MethodInfo methodInfo;
		object[] parameter = new object[1];

		public Parseable()
		{
			Type type = typeof (T);
			theObject = Activator.CreateInstance(type);
			methodInfo = type.GetMethod("Parse", new Type[] { typeof(string) });
		}

		public override T GetValue(XmlNode node)
		{
			if (node == null)
				throw new Exception("I can't parse a null value.");

			XmlNode localNode = node.SelectSingleNode(SelectString);
			return GetValueLocal(localNode);
		}


		public override T GetValueLocal(XmlNode node)
		{
			if (node == null || string.IsNullOrEmpty(node.InnerXml))
				return default(T);

			parameter[0] = node.InnerText;
			return (T)methodInfo.Invoke(theObject, parameter);			
		}
	}
}